#include "openglwidget.h"
#include <QKeyEvent>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QOpenGLContext>
#include <QAbstractAnimation>
#include <QDebug>
#include <cmath>
OpenGLWidget::OpenGLWidget(QWidget *parent)
    : QOpenGLWidget(parent), m_program(nullptr), m_cameraPos(0.0f, 0.0f, 5.0f), m_zoom(1.0f)
{
    setFocusPolicy(Qt::StrongFocus);
}

OpenGLWidget::~OpenGLWidget()
{
    makeCurrent();
    m_vbo_axes.destroy();
    delete m_program;
    doneCurrent();
}

void OpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // 黑色背景
    glEnable(GL_DEPTH_TEST);
    initShaders();
    initGeometry();
}

void OpenGLWidget::initShaders()
{
    m_program = new QOpenGLShaderProgram(this);

    const char *vertexShaderSource =
        "#version 330 core\n"
        "layout(location = 0) in vec3 aPos;\n"
        "layout(location = 1) in vec3 aColor;\n"
        "out vec3 fragColor;\n"
        "uniform mat4 model;\n"
        "uniform mat4 view;\n"
        "uniform mat4 projection;\n"
        "void main()\n"
        "{\n"
        "    gl_Position = projection * view * model * vec4(aPos, 1.0);\n"
        "    fragColor = aColor;\n"
        "}\n";

    const char *fragmentShaderSource =
        "#version 330 core\n"
        "in vec3 fragColor;\n"
        "out vec4 outColor;\n"
        "void main()\n"
        "{\n"
        "    outColor = vec4(fragColor, 1.0);\n"
        "}\n";

    m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
    m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
    m_program->link();

    if (!m_program->isLinked())
    {
        qDebug() << "Shader link error:" << m_program->log();
    }
}

void OpenGLWidget::initGeometry()
{
    // 定义坐标轴顶点数据 (X-红色, Y-绿色, Z-蓝色)
    float axesVertices[] = {
        // X轴 - 红色
        0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
        1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,

        // Y轴 - 绿色
        0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,

        // Z轴 - 蓝色
        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f};

    m_vao.create();
    m_vao.bind();

    m_vbo_axes.create();
    m_vbo_axes.bind();
    m_vbo_axes.allocate(axesVertices, sizeof(axesVertices));

    m_vao.release();
}

void OpenGLWidget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
    float aspect = w / (float)h;
    m_proj.setToIdentity();
    m_proj.perspective(45.0f, aspect, 0.1f, 100.0f);
}

void OpenGLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    m_program->bind();

    m_model.setToIdentity();
    m_model.rotate(m_rotationAngle, 0, 1, 0); // 外部控制的旋转
    float currentTime = m_timer.elapsed();
    m_model.rotate(currentTime / 50.0f, 0.0f, 1.0f, 0.0f); // 自转
    m_view.setToIdentity();
    m_view.translate(-m_cameraPos);

    m_program->setUniformValue("view", m_view);
    m_program->setUniformValue("projection", m_proj);
    m_program->setUniformValue("model", m_model);

    m_vao.bind();
    m_vbo_axes.bind();
    m_program->enableAttributeArray(0);
    m_program->setAttributeBuffer(0, GL_FLOAT, 0, 3, 6 * sizeof(float));
    m_program->enableAttributeArray(1);
    m_program->setAttributeBuffer(1, GL_FLOAT, 3 * sizeof(float), 3, 6 * sizeof(float));
    glDrawArrays(GL_LINES, 0, 6);
    m_vbo_axes.release();
    m_vao.release();

    m_program->release();
}

// ----------------- 控制接口 -----------------

void OpenGLWidget::setShowTriangle(bool show)
{
    m_showTriangle = show;
    update();
}

void OpenGLWidget::setShowSquare(bool show)
{
    m_showSquare = show;
    update();
}

void OpenGLWidget::setRotationAngle(float angle)
{
    m_rotationAngle = angle;
    update();
}

void OpenGLWidget::setColorFactor(float factor)
{
    m_colorFactor = factor;
    update();
}

// ----------------- 用户交互 -----------------

void OpenGLWidget::keyPressEvent(QKeyEvent *event)
{
    m_keys[event->key()] = true;
    update();
}

void OpenGLWidget::keyReleaseEvent(QKeyEvent *event)
{
    m_keys[event->key()] = false;
}

void OpenGLWidget::mousePressEvent(QMouseEvent *event)
{
    m_lastMousePos = QVector2D(event->pos());
}

void OpenGLWidget::mouseMoveEvent(QMouseEvent *event)
{
    QVector2D current(event->pos());
    QVector2D delta = current - m_lastMousePos;

    if (event->buttons() & Qt::LeftButton)
    {
        m_cameraPos.setX(m_cameraPos.x() - delta.x() * 0.01f);
        m_cameraPos.setY(m_cameraPos.y() + delta.y() * 0.01f);
        update();
    }
    m_lastMousePos = current;
}

void OpenGLWidget::wheelEvent(QWheelEvent *event)
{
    m_zoom += event->angleDelta().y() * 0.001f;
    m_zoom = qBound(0.1f, m_zoom, 10.0f);
    m_cameraPos.setZ(5.0f / m_zoom);
    update();
}